package com.yq.cp.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yq.cp.entity.common.ErrorCode;
import com.yq.cp.utils.JwtUtil;
import com.yq.cp.utils.RedisUtil;
import io.jsonwebtoken.Claims;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 鉴权过滤器 验证token
 */
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    private static final String AUTHORIZE_TOKEN = "token";
    private boolean sso=false;
//    @Value("${zh.permit_through}")
//    private List<String> list;
    @Resource
    RedisUtil redisUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1. 获取请求
        ServerHttpRequest request = exchange.getRequest();
        //2. 则获取响应
        ServerHttpResponse response = exchange.getResponse();
        //3. 如果是登录请求则放行
        List<String> list=new ArrayList<>();
        list.add("/manage/login");
        list.add("/manage/getToken");
        list.add("/manage/kl/redirect_url");
        list.add("/manage/nk/add/neet");
        list.add("/user/login");
        list.add("/user/wx/callback");
        list.add("/user/wx/callback/refund");
        list.add("/user/wx/member-callback");
        list.add("/user/productionMessage/recommend");
        list.add("/user/productionOperate/viewCounts");
        list.add("/user/agreement/list");
        list.add("/user/productionMessage/folderDetail");
        list.add("/user/productionMessage/list-self");
        list.add("/user/productionMessage/list-other");

        //4. 获取请求头
        HttpHeaders headers = request.getHeaders();
        //5. 请求头中获取令牌
        String token = headers.getFirst(AUTHORIZE_TOKEN);
        if (list.contains(request.getURI().getPath())) {
            if (token!=null && !token.equals("")){

                Claims claims = JwtUtil.parseJWT(token);
                String subject = claims.getSubject();
                ServerHttpRequest shr = null;

                //单点登录
                if (sso){
                    JSONObject jsonObject = JSON.parseObject(subject);
                    Long id = jsonObject.getLong("id");
                    String string = redisUtil.get(id + "-code").toString();
                    boolean b= jsonObject.getString("code").equals(string);
                    if (!b){
                        // 返回json
                        response.getHeaders().set("content-type","application/json;charset=utf-8");
                        // 初始容量：元素个数/0.75+1
                        Map<String,Object> map = new HashMap<>();
                        map.put("code", ErrorCode.QJ_1001.getCode());
                        map.put("msg", ErrorCode.QJ_1001.getMsg());

                        ObjectMapper objectMapper = new ObjectMapper();
                        byte[] bytes = new byte[0];
                        try {
                            bytes = objectMapper.writeValueAsBytes(map);
                        } catch (JsonProcessingException je) {
                            je.printStackTrace();
                        }
                        DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
                        return response.writeWith(Mono.just(dataBuffer));
                    }
                }


                try {
                    shr = request.mutate().header("tokenInfo", URLEncoder.encode(subject,"UTF-8")).build();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                exchange.mutate().request(shr).build();
            }

           return chain.filter(exchange);
        }

        //6. 判断请求头中是否有令牌
        if (StringUtils.isEmpty(token)) {
            // 返回json
            response.getHeaders().set("content-type","application/json;charset=utf-8");
            // 初始容量：元素个数/0.75+1
            Map<String,Object> map = new HashMap<>();
            map.put("code", ErrorCode.QJ_1001.getCode());
            map.put("msg", ErrorCode.QJ_1001.getMsg());

            ObjectMapper objectMapper = new ObjectMapper();
            byte[] bytes = new byte[0];
            try {
                bytes = objectMapper.writeValueAsBytes(map);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
            return response.writeWith(Mono.just(dataBuffer));
        }



        //9. 如果请求头中有令牌则解析令牌
        Claims claims = JwtUtil.parseJWT(token);
        //以下两行代码表示把token放入请求头中
        String subject = claims.getSubject();
        //单点登录
        if (sso){
            JSONObject jsonObject = JSON.parseObject(subject);
            Long id = jsonObject.getLong("id");
            String string = redisUtil.get(id + "-code").toString();
            boolean b= jsonObject.getString("code").equals(string);
            if (!b){
                // 返回json
                response.getHeaders().set("content-type","application/json;charset=utf-8");
                // 初始容量：元素个数/0.75+1
                Map<String,Object> map = new HashMap<>();
                map.put("code", ErrorCode.QJ_1001.getCode());
                map.put("msg", ErrorCode.QJ_1001.getMsg());

                ObjectMapper objectMapper = new ObjectMapper();
                byte[] bytes = new byte[0];
                try {
                    bytes = objectMapper.writeValueAsBytes(map);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
                return response.writeWith(Mono.just(dataBuffer));
            }
        }

        try {




            ServerHttpRequest shr = request.mutate().header("tokenInfo", URLEncoder.encode(subject,"UTF-8")).build();
            exchange.mutate().request(shr).build();
        } catch (Exception e) {
            e.printStackTrace();
            // 返回json
            response.getHeaders().set("content-type","application/json;charset=utf-8");
            // 初始容量：元素个数/0.75+1
            Map<String,Object> map = new HashMap<>();
            map.put("code", ErrorCode.QJ_1002.getCode());
            map.put("msg", ErrorCode.QJ_1002.getMsg());

            ObjectMapper objectMapper = new ObjectMapper();
            byte[] bytes = new byte[0];
            try {
                bytes = objectMapper.writeValueAsBytes(map);
            } catch (JsonProcessingException je) {
                je.printStackTrace();
            }
            DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
            return response.writeWith(Mono.just(dataBuffer));
        }
        //12. 放行
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

